(function (fruit, util) {
    fruit.define("fruit.io.WebSocket", {
        singleton: true,
        events: ["OPEN", "MESSAGE", "CLOSE", "SENT"],
        properties: {
            url: {
                value: null
            }
        },
        methods: {
            init: function () {

            },
            connect: function (inURL, callback) {
                var url = inURL || this.url();
                if (url && ("WebSocket" in window)) {
                    this.url(url);
                    this.ws = new WebSocket(url);
                    this._registerEvent();
                    callback && callback.call(this, this.ws);
                }
            },
            _registerEvent: function () {
                var ws = this.ws;
                var self = this;
                ws.onopen = function (socket) {
                    self.fire("OPEN", {state: socket.readyState});
                }
                ws.onmessage = function (msg) {
                    self.__executeProcessors(msg);
                    self.fire("MESSAGE", {data: msg.data});
                }
                ws.onclose = function (socket) {
                    self.fire("CLOSE", {state: socket.readyState});
                }
            },
            send: function (value) {
                this.ws.send(value);
                this.fire("SENT", {data: value});
            },
            close: function () {
                this.ws.close()
            },
            __executeProcessors: function (args) {
                if (this.processorMap && !util.isEmpty(this.processorMap)) {
                    var processorMap = this.processorMap;
                    try {
                        var data = JSON.parse(args.data);
                        if (util.isObject(data)) {
                            util.each(processorMap, function (processor, key) {
                                if (key in data) {
                                    processor.action.call(processor.context, data);
                                }
                            })
                        }

                    } catch (e) {

                    }
                }

            },
            registerProcessor: function (key, fn, context) {
                var processorMap = this.processorMap = this.processorMap || {};
                //var processor = processorMap[key] = processorMap[key] | [];
                //processor.push(fn);
                processorMap[key] = {
                    action: fn,
                    context: context || this
                };
            },
            removeProcessor: function (key) {
                delete this.processorMap[key];
            }

        }
    })

})(fruit, fruit.util);